package vue_controleur;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JMenuBar;

import commande.commandes.*;

/**
 * La class IHMImp implement l'interface IHM mais aussi KeyListener et MouseListener pour la recuperation des evenements genere par l'utilisateur.
 */

public class IHMImpl implements IHM, KeyListener, MouseListener, ActionListener {
	private JFrame _fenetre;
	private JTextPane _jText;
	private char _carLu;
	private Curseur _curseur;
	private Boolean _ctrlActif=false;
	private Boolean _shiftActif=false;
	private int _debutSelect;
	private int _finSelect;
	private int _nouveauPlacement;
	private Boolean _sup;
	
	private int _largeur = 300;
	private int _longeur = 400;
	
	private SaisirTexte _saisie = new SaisirTexte();
	private Selectionner _selection = new Selectionner();
	private Deplacement _deplacement = new Deplacement();
	private Supprimer _supprime = new Supprimer();
	private Copier _copier = new Copier();
	private Coller _coller = new Coller();
	private Couper _couper = new Couper();
	private Enregistrer _enregistrer = new Enregistrer();
	private Rejouer _rejouer = new Rejouer();
	private Undo _undo = new Undo();
	private Redo _redo =new Redo();
	
	
	private JMenuBar _barre_menu = new JMenuBar();
	private JMenu _menu_fichier = new JMenu("Fichier");
	private JMenuItem _menu_fichier_ouvrir = new JMenuItem("Ouvrir");
	private JMenuItem _menu_fichier_fermer = new JMenuItem("Fermer");
	private JMenuItem _menu_fichier_quitter = new JMenuItem("Quitter");
	
	private JMenu _menu_edition = new JMenu("Edition");
	private JMenuItem _menu_edition_copier = new JMenuItem("Copier");
	private JMenuItem _menu_edition_couper = new JMenuItem("Couper");
	private JMenuItem _menu_edition_coller = new JMenuItem("Coller");
	
	private JMenu _menu_enregistre = new JMenu("Enregistre");
	private JMenuItem _menu_edition_lance = new JMenuItem("Lancer");
	private JMenuItem _menu_edition_rejoue = new JMenuItem("Rejouer");
	

	
	/**
	 * Constructeur de la class qui cree la fenetre.
	 */
	public IHMImpl(){
		_fenetre = new JFrame("MiniEditeur - Mauduit & Marginier");
		_fenetre.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		_fenetre.setSize(_longeur, _largeur);
		_fenetre.setJMenuBar(_barre_menu);
		_jText = new JTextPane();
		_jText.setPreferredSize( new Dimension(_longeur, _largeur) );
		_jText.setEditable(false);
		_jText.addMouseListener(this);
		_jText.addKeyListener(this);
		_jText.setText("|");
		_fenetre.getContentPane().add(_jText);
		_fenetre.pack();
		_fenetre.setVisible(true);
		
		// ajout du curseur
		_curseur = new Curseur(0, _jText, _fenetre);
		_curseur.start();
		
		// ajout des menus dans la barre
		_barre_menu.add(_menu_fichier);
		_barre_menu.add(_menu_edition);
		_barre_menu.add(_menu_enregistre);
		
		// Action listener sur les elements du menu
		_menu_fichier_ouvrir.addActionListener(this);
		_menu_fichier_fermer.addActionListener(this);
		_menu_fichier_quitter.addActionListener(this);
		_menu_edition_copier.addActionListener(this);
		_menu_edition_couper.addActionListener(this);
		_menu_edition_coller.addActionListener(this);
		_menu_edition_lance.addActionListener(this);
		_menu_edition_rejoue.addActionListener(this);
		
		// ajout des items du menu fichier
		_menu_fichier.add(_menu_fichier_ouvrir);
		_menu_fichier.add(_menu_fichier_fermer);
		_menu_fichier.add(_menu_fichier_quitter);

		// ajout des items du menu edition
		_menu_edition.add(_menu_edition_copier);
		_menu_edition.add(_menu_edition_couper);
		_menu_edition.add(_menu_edition_coller);
		
		// ajout des items du menu enregistre
		_menu_enregistre.add(_menu_edition_lance);
		_menu_enregistre.add(_menu_edition_rejoue);
		
		// cache l'option rejouer au debut
		_menu_edition_rejoue.setVisible(false);
		
		//changement d'icone en haut a gauche car le symbole java c'est moisi
		BufferedImage icone= new BufferedImage(99, 99, BufferedImage.TYPE_INT_RGB);
	    Graphics2D g= icone.createGraphics();
	    g.setColor(Color.BLUE);
	    g.fillRect(0, 0, 33, 99);
	    g.setColor(Color.WHITE);
	    g.fillRect(33, 0, 33, 99);
	    g.setColor(Color.RED);
	    g.fillRect(66, 0, 33, 99);
	    _fenetre.setIconImage(icone);
	}
	
	/**
	 * Fonction qui permet d'actualise le contenu de l'IHM
	 * @param text StringBuffer Contient le text a affiche a dans la fenetre.
	 */
	public void refreshTexte(StringBuffer text){
		text.insert(_curseur.getEmplacement(), '|');
		_jText.setText(text.toString());
	}
	
	private void refreshTexteSansCurseur(){
		StringBuffer tex = new StringBuffer(_jText.getText());
		tex.deleteCharAt(_curseur.getEmplacement());
		_jText.setText(tex.toString());
	}
	
	public void actualiseSelection(int deb, int fin, boolean placementCurDevantSelection){
		if(placementCurDevantSelection) _jText.select(deb+1, fin+1);
		else _jText.select(deb, fin);
	}
	
	public void enregistre(Boolean actif){
		if(!actif){
			_menu_edition_lance.setText("Lancer");
			_menu_edition_rejoue.setVisible(true);
		}else{
			_menu_edition_lance.setText("Stop");
			_menu_edition_rejoue.setVisible(false);
		}
	}
	
	//--------------------------------------------------------------------------------------------------
	//--------------------------			Getter/Setter			------------------------------------
	//--------------------------------------------------------------------------------------------------
	
	public Curseur getCurseur(){
		return _curseur;
	}
	public int getDebutSelect(){
		return _debutSelect;
	}
	public int getFinSelect(){
		return _finSelect;
	}
	public int getNouveauPlacement(){
		return _nouveauPlacement;
	}
	public Boolean getSup(){
		return _sup;
	}

	/**
	 * Getter sur le dernier caractere tape.
	 * @return _carlu
	 */
	public char getTexte(){
		return _carLu;
	}
	
	//--------------------------------------------------------------------------------------------------
	//--------------------------			clavier/souris			------------------------------------
	//--------------------------------------------------------------------------------------------------
	
	
		/**
		 * Cette fonction recupere l'evenement de clic de souris sur la fenetre.
		 * @param arg0 MouseEvent Permet d'avoir les informations necessaires sur cet evenement. 
		 */
		public void mouseClicked(MouseEvent arg0) {
			// TODO Auto-generated method stub

		}
		
		/**
		 * Cette fonction recupere l'evenement d'enfoncement de touches au clavier.
		 * @param arg0 KeyEvent Permet notamment de connaitre la touche pressee.
		 */
		public void keyPressed(KeyEvent arg0) {
			if(!_curseur.getClic()){
				if (arg0.getKeyCode() == KeyEvent.VK_CONTROL) {
				    _ctrlActif = true;
				}else if(arg0.getKeyCode() == KeyEvent.VK_SHIFT){
					_shiftActif = true;
				}
				
				else if(_ctrlActif){
					switch(arg0.getKeyCode()){
						case 67 : _copier.execute();
							break;//ctrl + c
						case 86 : _coller.execute();
							break;//ctrl + v
						case 88 : _couper.execute();
							break;//ctrl + x
						case 90 : _undo.execute();
							break;//ctrl + z
						case 89 : _redo.execute();
							break;//ctrl + y
						default : ;
					}
					
				}else if(_shiftActif){
					_carLu = arg0.getKeyChar();
					_saisie.execute();
				}else{
					switch(arg0.getKeyCode()){
						case 39 : _nouveauPlacement=_curseur.getEmplacement()+1;
								if(_nouveauPlacement>=_jText.getText().length()-1) _nouveauPlacement=_jText.getText().length()-1;
								_deplacement.execute(); 
								break;//fleche droite
								
						case 40 : break;//fleche bas
						case 38 : break;//fleche haut
						case 37 : _nouveauPlacement=_curseur.getEmplacement()-1;
								if(_nouveauPlacement<0) _nouveauPlacement=0;
								_deplacement.execute(); 
								break;//fleche gauche
						case 8 : _sup=true; _supprime.execute(); break;//sup
						case 127 : _sup=false; _supprime.execute(); break;//del
						default : _carLu = arg0.getKeyChar(); _saisie.execute();
					}
				}
			}
		}
	
	@Override
	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mousePressed(MouseEvent arg0) {
		_curseur.clicActif();
		int v=_jText.getCaretPosition();
		refreshTexteSansCurseur();
		if(v>_curseur.getEmplacement()) v--;
		_jText.setCaretPosition(v);
	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
		_debutSelect=_jText.getSelectionStart();
		_finSelect=_jText.getSelectionEnd();
		_nouveauPlacement = _finSelect+1;
		_selection.execute();
		
		_nouveauPlacement = _jText.getCaretPosition(); // _jText.getCaret().getMark();
		if(_nouveauPlacement>=_jText.getText().length()) _nouveauPlacement=_jText.getText().length();
		_deplacement.execute();
		
		if(_debutSelect!=_finSelect){
			if(_curseur.getEmplacement()<=_debutSelect) _jText.select(_debutSelect+1, _finSelect+1);
			else _jText.select(_debutSelect, _finSelect);
		}
		_curseur.clicDesactif();
	}

	@Override
	public void keyReleased(KeyEvent arg0) {
		if (arg0.getKeyCode() == KeyEvent.VK_CONTROL) {
		    _ctrlActif = false;
		}else if(arg0.getKeyCode() == KeyEvent.VK_SHIFT){
			_shiftActif=false;
		}
		
	}

	@Override
	public void keyTyped(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == _menu_edition_couper) {
            _couper.execute();
        }
		if (e.getSource() == _menu_edition_copier) {
            _copier.execute();
        }
		if (e.getSource() == _menu_edition_coller) {
            _coller.execute();
        }
        if (e.getSource() == _menu_fichier_quitter) {
            System.exit(0);
        }
        if (e.getSource() == _menu_edition_lance) {
        	_enregistrer.execute();
        }
        if (e.getSource() == _menu_edition_rejoue) {
        	_rejouer.execute();
        }
	}
}
